﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
using System.Globalization;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using Microsoft.Research.DynamicDataDisplay;
using System.Threading;
using System.Reflection;
using System.IO;
using System.Windows.Threading;
using Microsoft.Research.DynamicDataDisplay.ViewportRestrictions;
using System.Collections.ObjectModel;
using Microsoft.Research.DynamicDataDisplay.PointMarkers;

namespace PMisuseAn
{
    /// <summary>
    /// Interaction logic for AdaptationMgtConfigWindow.xaml
    /// </summary>
    public partial class AdaptationMgtConfigWindow : Window
    {
        //public static double contextChangeDampingFactor;
        public static double attributeValueDampingFactor;
        //public static double threatFreqDampingFactor;
        public static double attributeGenDampingFactor;

        //public static double kcDelta;
        public static double kv;
        //public static double kt;
        public static double kg;

        //public static bool isPveContextChangeCorrelation;
        public static bool isPveAttributeValueCorrelation;
        //public static bool isPveThreatFreqCorrelation;
        public static bool isPveAttGenCorrelation;

        //public static bool contextChangeExp;
        public static bool attributeValueExp;
        //public static bool threatFreqExp;
        public static bool attGenExp;

        public static double ignoreThreshExpectedUtility;
        public static double reactThreshExpectedUtility;
        public static double preventThreshExpectedUtility;

        public static double metaReactThreshExpectedUtility;
        public static double metaPreventThreshExpectedUtility;
        public static double metaTerminateThreshExpectedUtility;

        public static double[] x_attGen;
        public static double[] y_attGen;
        //public static double[] x_ThreatFreq;
        //public static double[] y_ThreatFreq;
        public static double[] x_AttVal;
        public static double[] y_AttVal;
        //public static double[] x_CDeltaFreq;
        //public static double[] y_CDeltaFreq;
        
        private static bool isreload = false;
        public static bool isAdaptationConfigured = false;
        public AdaptationMgtConfigWindow()
        {
            InitializeComponent();
            this.reloadVars();
            isAdaptationConfigured = true;
        }

        private void reloadVars()
        {
            isreload = true;
            ignoreRun.Text = "" + ignoreThreshExpectedUtility;
            reactRun1.Text = "" + ignoreThreshExpectedUtility;
            reactRun2.Text = "" + reactThreshExpectedUtility;
            reactRun3.Text = "" + reactThreshExpectedUtility;
            preventRun.Text = "" + preventThreshExpectedUtility;
            preventRun1.Text = "" + preventThreshExpectedUtility;

            metaReactRun.Text = "" + metaReactThreshExpectedUtility;
            metaPreventRun.Text = "" + metaPreventThreshExpectedUtility;
            metaTerminateRun.Text = "" + metaTerminateThreshExpectedUtility;

            ignore_slider.Value = ignoreThreshExpectedUtility * 10;
            prevent_slider.Value = preventThreshExpectedUtility * 10;
            react_slider.Value = reactThreshExpectedUtility * 10;

            metaReactSlider.Value = metaReactThreshExpectedUtility * 10;
            metaPreventSlider.Value = metaPreventThreshExpectedUtility * 10;
            metaTerminateSlider.Value = metaTerminateThreshExpectedUtility * 10;

            att_value_correlation_damping_factor_tb.Text = "" + attributeValueDampingFactor;
            att_generality_correlation_damping_factor_tb.Text = "" + attributeGenDampingFactor;

            kg_tb.Text = "" + kg;
            kv_tb.Text = "" + kv;           
            
            if (attributeValueExp == true)
            {
                val_att_exp_cb.IsChecked = true;
            }
            else
            {
                val_att_exp_cb.IsChecked = false;
            }
                        

            if (attGenExp == true)
            {
                gen_att_exp_cb.IsChecked = true;
            }
            else
            {
                gen_att_exp_cb.IsChecked = false;
            }

            if (isPveAttGenCorrelation == true)
            {
                att_gen_cor_pve_rb.IsChecked = true;
            }
            else
            {
                att_gen_cor_nve_rb.IsChecked = true;
            } 
                
            if (isPveAttributeValueCorrelation == true)
            {
                value_of_att_cor_pve_rb.IsChecked = true;
            }
            else
            {
                value_of_att_cor_nve_rb.IsChecked = true;
            }

            isreload = false;


        }
        
        private void keyPressedFreqCC(object sender, KeyEventArgs e)
        {
            process();
        }
        private void process()
        {     
            if (att_value_correlation_damping_factor_tb != null)
            {
                string attributeValueDampingFactor_s = att_value_correlation_damping_factor_tb.Text;
                //attributeValueDampingFactor = 0;
                double number1;
                if (Double.TryParse(attributeValueDampingFactor_s, out number1))
                {
                    attributeValueDampingFactor = Convert.ToDouble(attributeValueDampingFactor_s);
                }
            }
            
            if (att_generality_correlation_damping_factor_tb != null)
            {
                string attributeGenDampingFactor_s = att_generality_correlation_damping_factor_tb.Text;
                //attributeGenDampingFactor = 0;
                double number3;
                if (Double.TryParse(attributeGenDampingFactor_s, out number3))
                {
                    attributeGenDampingFactor = Convert.ToDouble(attributeGenDampingFactor_s);
                }

            }
            if (isreload)
            {                
                if (val_att_exp_cb != null)
                {
                    if (val_att_exp_cb.IsChecked == true)
                    {
                        attributeValueExp = true;
                    }
                }
                
                if (gen_att_exp_cb != null)
                {
                    if (gen_att_exp_cb.IsChecked == true)
                    {
                        attGenExp = true;
                    }
                }  
            }
            else
            {                
                if (val_att_exp_cb != null)
                {
                    if (val_att_exp_cb.IsChecked == true)
                    {
                        attributeValueExp = true;
                    }
                    if (val_att_exp_cb.IsChecked == false)
                    {
                        attributeValueExp = false;
                    }
                }
                
                if (gen_att_exp_cb != null)
                {
                    if (gen_att_exp_cb.IsChecked == true)
                    {
                        attGenExp = true;
                    }
                    if (gen_att_exp_cb.IsChecked == false)
                    {
                        attGenExp = false;
                    }
                }  
            }
                  
            if (value_of_att_cor_pve_rb != null)
            {
                if (value_of_att_cor_pve_rb.IsChecked == true)
                {
                    isPveAttributeValueCorrelation = true;
                }
                else if (value_of_att_cor_nve_rb.IsChecked == true)
                {
                    isPveAttributeValueCorrelation = false;
                }
            }           
        
            if (att_gen_cor_pve_rb != null)
            {
                if (att_gen_cor_pve_rb.IsChecked == true)
                {
                    isPveAttGenCorrelation = true;
                }
                else if (att_gen_cor_nve_rb.IsChecked == true)
                {
                    isPveAttGenCorrelation = false;
                }
            }
            
            if (plotter1 != null && plotter3 != null)
            {
                ClearLines();
                reloadAttValueGraph();
                reloadAttGenGraph();
            }

            if (ignoreRun != null && preventRun1 != null && preventRun != null
                && reactRun1 != null && reactRun2 != null && reactRun3 != null)
            {
                ignoreRun.Text = "" + ignoreThreshExpectedUtility;
                reactRun1.Text = "" + ignoreThreshExpectedUtility;
                reactRun2.Text = "" + reactThreshExpectedUtility;
                reactRun3.Text = "" + reactThreshExpectedUtility;
                preventRun.Text = "" + preventThreshExpectedUtility;
                preventRun1.Text = "" + preventThreshExpectedUtility;                 
            }

            if (metaReactRun != null && metaPreventRun != null && metaTerminateRun != null)
            {
                metaReactRun.Text = "" + metaReactThreshExpectedUtility;
                metaPreventRun.Text = "" + metaPreventThreshExpectedUtility;
                metaTerminateRun.Text = "" + metaTerminateThreshExpectedUtility;
            }
        }

        private void reloadAttGenGraph()
        {
            const int N = 101;

            // Prepare data in arrays for context change plot
            x_attGen = new double[N];
            y_attGen = new double[N];

            if (isPveAttGenCorrelation)
            {
                double jx = 0;
                int index = 0;
                while (jx <= 1)
                {
                    x_attGen[index] = jx;
                    if (attGenExp == true)
                    {
                        y_attGen[index] = Math.Exp(jx * attributeGenDampingFactor);
                    }
                    else
                    {
                        y_attGen[index] = jx * attributeGenDampingFactor;
                    }
                    //Console.WriteLine("NO. "+index+" X: " + x[index] + " Y: " + y[index]);
                    //Console.WriteLine("---------------");

                    jx = jx + 0.01;
                    index = index + 1;
                }
            }
            else
            {
                double jx = 0;
                int index = 0;
                while (jx <= 1)
                {
                    x_attGen[index] = jx;
                    if (attGenExp == true)
                    {
                        y_attGen[N - index - 1] = Math.Exp(jx * attributeGenDampingFactor);
                    }
                    else
                    {
                        y_attGen[N - index - 1] = jx * attributeGenDampingFactor;
                    }
                    //Console.WriteLine("NO. " + index + " X: " + x[index] + " Y: " + y[N - index - 1]);
                    //Console.WriteLine("---------------");

                    jx = jx + 0.01;
                    index = index + 1;
                }
            }

            // Add data sources:
            var yDataSource = new ObservableDataSource<double>(y_attGen);
            yDataSource.SetYMapping(Y => Y);
            //yDataSource.AddMapping(ShapeElementPointMarker.ToolTipTextProperty,
            //    Y => string.Format("Value is {0}", Y));

            var xDataSource = new ObservableDataSource<double>(x_attGen);
            xDataSource.SetXMapping(X => X);

            CompositeDataSource compositeDataSource = new CompositeDataSource(xDataSource, yDataSource);

            //plotter.Viewport.Restrictions.Add(new PhysicalProportionsRestriction { ProportionRatio = 1 });

            // adding graph to plotter
            PenDescription pd = new PenDescription("U(Ga)");
            pd.LegendItem.FontSize = 10;
            plotter3.AddLineGraph(compositeDataSource,
                new Pen(Brushes.White, 1),
                new SampleMarker(),
                pd);
        }
        
        private void reloadAttValueGraph()
        {            
            const int N = 101;

            // Prepare data in arrays for context change plot
            x_AttVal = new double[N];
            y_AttVal = new double[N];

            if (isPveAttributeValueCorrelation)
            {
                double jx = 0;
                int index = 0;
                while (jx <= 1)
                {
                    x_AttVal[index] = jx;
                    if (attributeValueExp == true)
                    {
                        y_AttVal[index] = Math.Exp(jx * attributeValueDampingFactor);
                    }
                    else
                    {
                        y_AttVal[index] = jx * attributeValueDampingFactor;
                    }
                    //Console.WriteLine("NO. "+index+" X: " + x[index] + " Y: " + y[index]);
                    //Console.WriteLine("---------------");

                    jx = jx + 0.01;
                    index = index + 1;
                }
            }
            else
            {
                double jx = 0;
                int index = 0;
                while (jx <= 1)
                {
                    x_AttVal[index] = jx;
                    if (attributeValueExp == true)
                    {
                        y_AttVal[N - index - 1] = Math.Exp(jx * attributeValueDampingFactor);
                    }
                    else
                    {
                        y_AttVal[N - index - 1] = jx * attributeValueDampingFactor;
                    }
                    //Console.WriteLine("NO. " + index + " X: " + x[index] + " Y: " + y[N - index - 1]);
                    //Console.WriteLine("---------------");

                    jx = jx + 0.01;
                    index = index + 1;
                }
            }

            // Add data sources:
            var yDataSource = new ObservableDataSource<double>(y_AttVal);
            yDataSource.SetYMapping(Y => Y);
            //yDataSource.AddMapping(ShapeElementPointMarker.ToolTipTextProperty,
            //    Y => string.Format("Value is {0}", Y));

            var xDataSource = new ObservableDataSource<double>(x_AttVal);
            xDataSource.SetXMapping(X => X);

            CompositeDataSource compositeDataSource = new CompositeDataSource(xDataSource, yDataSource);

            //plotter.Viewport.Restrictions.Add(new PhysicalProportionsRestriction { ProportionRatio = 1 });

            // adding graph to plotter
            PenDescription pd = new PenDescription("U(Va)");
            pd.LegendItem.FontSize = 10;
            plotter1.AddLineGraph(compositeDataSource,
                new Pen(Brushes.White, 1),
                new SampleMarker(),
                pd); 
        }

        public void ClearLines()
        {            
            var lgc1 = new Collection<IPlotterElement>();
            foreach (var x in plotter1.Children)
            {
                if (x is LineGraph || x is ElementMarkerPointsGraph)
                    lgc1.Add(x);
            }

            foreach (var x in lgc1)
            {
                plotter1.Children.Remove(x);
            }
            
            var lgc3 = new Collection<IPlotterElement>();
            foreach (var x in plotter3.Children)
            {
                if (x is LineGraph || x is ElementMarkerPointsGraph)
                    lgc3.Add(x);
            }

            foreach (var x in lgc3)
            {
                plotter3.Children.Remove(x);
            }
        }

        private void metaReactSliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            metaReactThreshExpectedUtility = (metaReactSlider.Value);
            metaReactRun.Text = "" + metaReactThreshExpectedUtility;
        }
        private void metaPreventSliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            metaPreventThreshExpectedUtility = (metaPreventSlider.Value);
            metaPreventRun.Text = "" + metaPreventThreshExpectedUtility;
        }
        private void metaTerminateSliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            metaTerminateThreshExpectedUtility = (metaTerminateSlider.Value);
            metaTerminateRun.Text = "" + metaTerminateThreshExpectedUtility;
        }

        private void ignoreSliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            ignoreThreshExpectedUtility = (ignore_slider.Value)/10;

            if(ignoreThreshExpectedUtility >reactThreshExpectedUtility)
            {
                reactThreshExpectedUtility = ignoreThreshExpectedUtility;
                react_slider.Value = ignoreThreshExpectedUtility *10;                
            }

            if (ignoreThreshExpectedUtility > preventThreshExpectedUtility)
            {
                preventThreshExpectedUtility = ignoreThreshExpectedUtility;
                prevent_slider.Value = ignoreThreshExpectedUtility*10;
            }

            ignoreRun.Text = "" + ignoreThreshExpectedUtility;
            reactRun1.Text = "" + ignoreThreshExpectedUtility;
            reactRun2.Text = "" + reactThreshExpectedUtility;
            reactRun3.Text = "" + reactThreshExpectedUtility;
            preventRun.Text = "" + preventThreshExpectedUtility;
            preventRun1.Text = "" + preventThreshExpectedUtility;             
        }

        private void reactSliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            reactThreshExpectedUtility = (react_slider.Value) / 10;

            if (reactThreshExpectedUtility < ignoreThreshExpectedUtility)
            {
                ignoreThreshExpectedUtility = reactThreshExpectedUtility;
                ignore_slider.Value = reactThreshExpectedUtility * 10;
            }

            if (reactThreshExpectedUtility > preventThreshExpectedUtility)
            {
                preventThreshExpectedUtility = reactThreshExpectedUtility;
                prevent_slider.Value = reactThreshExpectedUtility * 10;
            }

            ignoreRun.Text = "" + ignoreThreshExpectedUtility;
            reactRun1.Text = "" + ignoreThreshExpectedUtility;
            reactRun2.Text = "" + reactThreshExpectedUtility;
            reactRun3.Text = "" + reactThreshExpectedUtility;
            preventRun.Text = "" + preventThreshExpectedUtility;
            preventRun1.Text = "" + preventThreshExpectedUtility;
        }

        private void preventSliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            preventThreshExpectedUtility = (prevent_slider.Value)/10;

            if (preventThreshExpectedUtility < ignoreThreshExpectedUtility)
            {
                ignoreThreshExpectedUtility = preventThreshExpectedUtility;
                ignore_slider.Value = preventThreshExpectedUtility*10;
            }

            if (preventThreshExpectedUtility < reactThreshExpectedUtility)
            {
                reactThreshExpectedUtility = preventThreshExpectedUtility;
                react_slider.Value = preventThreshExpectedUtility*10;
            }

            ignoreRun.Text = "" + ignoreThreshExpectedUtility;
            reactRun1.Text = "" + ignoreThreshExpectedUtility;
            reactRun2.Text = "" + reactThreshExpectedUtility;
            reactRun3.Text = "" + reactThreshExpectedUtility;
            preventRun.Text = "" + preventThreshExpectedUtility;
            preventRun1.Text = "" + preventThreshExpectedUtility; 

        }

        private void close_b_Click(object sender, RoutedEventArgs e)
        {
            //string kc_s = kc_tb.Text;
            //double number1;
            //if (Double.TryParse(kc_s, out number1))
            //{
            //    kcDelta = Convert.ToDouble(kc_s);
            //}

            string kv_s = kv_tb.Text;
            double number2;
            if (Double.TryParse(kv_s, out number2))
            {
                kv = Convert.ToDouble(kv_s);
            }

            //string kt_s = kt_tb.Text;
            //double number3;
            //if (Double.TryParse(kt_s, out number3))
            //{
            //    kt = Convert.ToDouble(kt_s);
            //}

            string kg_s = kg_tb.Text;
            double number4;
            if (Double.TryParse(kg_s, out number4))
            {
                kg = Convert.ToDouble(kg_s);
            }

            this.Close();
        }

        private void cb_Checked(object sender, RoutedEventArgs e)
        {
            process();
        }

    }


    public class SampleMarker : ShapeElementPointMarker
    {
        public override UIElement CreateMarker()
        {
            Canvas result = new Canvas()
            {
                Width = 10,
                Height = Size
            };
            result.Width = Size/2;
            result.Height = Size/2;
            result.Background = Brush;
            if (ToolTipText != String.Empty)
            {
                ToolTip tt = new ToolTip();
                tt.Content = ToolTipText;
                result.ToolTip = tt;
            }
            return result;
        }

        public override void SetPosition(UIElement marker, Point screenPoint)
        {
            Canvas.SetLeft(marker, screenPoint.X - Size / 2);
            Canvas.SetTop(marker, screenPoint.Y - Size / 2);
        }
    }

}
